package com.lanou3g.code0417.tickets;

/**
 * Created by dllo on 18/4/17.
 */

/*
* 线程安全就会慢，线程不安全就会快SB在单线程中效率快，多线程中就会拼错
* 为了解决线程安全问题，java引进了同步机制：synchronized
*
* 语法：sychronized(lock){
*
* //只能一时间由一个线程访问
*
* }
* 大括号内的代码，在同一时间，只能被一个线程调用，即使线程在大括号内停止了，其他线程也无法进入到大括号内
*
* 小括号内 我们称之为锁对象，可以是任意的对象 但是要注意，成为锁对象的对象，不能再改变了，一般的，我们都会为锁对象
* 加上final 防止他被改变
*
* 锁越小效率越高
*
* */



//票务中心
public class TicketOffice {

    private int tickets = 10000;  //有100张票
    private final Object lock = new Object();
    // 返回值代表是否还有票
    public boolean sellTicket(){

//synchronized (){}大括号中的代码，只要有一个线程进去执行，执行完毕才会换下一个线程
        // 什么都能成为锁 String  Thread Integer等，锁前一般都加final
        synchronized (lock){  // 进入线程后，先检查锁是否锁上 若锁前不加final，可以换锁
            //lock = new String();  //改锁，顺序又会出错
        if (tickets <= 0){
            return false;
        }

//        try {
//            //让当前线程停止100 毫秒
//            Thread.sleep(100);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
        tickets --;

//        int a = tickets -1;   会导致比正常多卖   线程会在任意处停止，换另外的线程执行
//        tickets = a;

        //Thread.currentThread().getName() 打印当前线程
        System.out.println(Thread.currentThread().getName() +"卖出一张票,还剩："+tickets+"张");
        return true;

    }
}

    //在方法的返回值前，可以加上synchronized 关键字，相当于把整个方法都放在同步代码块中
    // 不需要写锁对象，这时，锁对象是 类名.class TicketOffice.class (这个类 的类对象JVM加载这个类时，自动创建)
    // 不推荐使用
    public synchronized void fun(){
        StringBuilder builder;
        //builder.append();  // 不加锁，不安全但效率高
       // StringBuffer buffer;  // 加锁 安全但牺牲效率

    }


}
